package com.zzq.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zzq.domain.dto.SmileClientDTO;
import com.zzq.domain.entity.SmileClient;
import com.zzq.domain.entity.SmileClientDelivery;
import com.zzq.domain.entity.SmileCoupon;
import com.zzq.domain.search.ClientDeliverySearchParamet;
import com.zzq.enumerate.OssPathEnum;
import com.zzq.enumerate.RedisKeyEnum;
import com.zzq.exception.LoginException;
import com.zzq.exception.NormalException;
import com.zzq.exception.SwitchException;
import com.zzq.result.SmileResult;
import com.zzq.security.ClientSecurityDTO;
import com.zzq.security.ex.NoUserAuthenticationException;
import com.zzq.security.util.UserUtil;
import com.zzq.service.ClientService;
import com.zzq.service.SmileAlbumService;
import com.zzq.service.SmileClientDeliveryService;
import com.zzq.service.SmileCouponService;
import com.zzq.subservice.ClientDeliverySubService;
import com.zzq.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ClientServiceImpl implements ClientService {

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.appsecret}")
    private String appsecret;

    @Value("${wx.login.url}")
    private String loginUrl;

    @Autowired
    private OssFileUtil ossFileUtil;

    @Autowired
    private AccessTokenUtil accessTokenUtil;

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    SmileClientServiceImpl smileClientService;
    @Autowired
    SmileAlbumService smileAlbumService;
    @Autowired
    SmileCouponService couponService;
    @Autowired
    SmileClientDeliveryService deliveryService;

    @Autowired
    ClientDeliverySubService clientDeliverySubService;
    @Autowired
    RedisCache redisCache;
    @Override
    @Transactional
    public SmileResult wxLogin(String code,  String phoneCode) {
        Map<String,Object> wxMap=new HashMap<>();
        wxMap.put("appid", appid);
        //小程序secret
        wxMap.put("secret", appsecret);
        //小程序端返回的code
        wxMap.put("js_code", code);
        wxMap.put("grant_type", "authorization_code");

        //获取openId
        String openidRes = HttpUtil.createGet(loginUrl).form(wxMap).execute().body();
        JSONObject openidJson = JSON.parseObject(openidRes);
        String openId = openidJson.getString("openid");
        String phoneNumber;
        //获取手机号
        try {
            phoneNumber =accessTokenUtil.getWxPhoneNum(phoneCode);
        }catch (SwitchException e){
            phoneNumber=null;
        }

        try {
            //已有登录信息
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(openId, "");
            Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
            SmileClient user = ((ClientSecurityDTO) authenticate.getPrincipal()).getUser();
            String token = JwtUtil.createJWT(String.valueOf(user.getId()));
            HashMap<String,Object> map=new HashMap<>();
            map.put("token", token);
            map.put("user", JSON.toJSONString(user));
            map.put("status",true);
            redisCache.setCacheObject(RedisKeyEnum.SMILE_CLIENT_LOGIN.key(user.getId()), user,7200);
            return SmileResult.sucess("登录成功",map);
        } catch (AuthenticationException exception) {
            //第一次登录
            if (exception instanceof NoUserAuthenticationException) {
                SmileClient smileClient = new SmileClient();
                String clientNo = smileClientService.getClientNo();
                smileClient.setClientNo(clientNo);
                smileClient.setOpenId(openId);
                smileClient.setClientPhone(phoneNumber);
                smileClientService.save(smileClient);
                String token = JwtUtil.createJWT(String.valueOf(smileClient.getId()));
                HashMap<String,Object> map=new HashMap<>();
                map.put("token", token);
                map.put("user", JSON.toJSONString(smileClient));
                map.put("status",false);
                redisCache.setCacheObject(RedisKeyEnum.SMILE_CLIENT_LOGIN.key(smileClient.getId()) , smileClient);
                return SmileResult.sucess("注册成功",map);
            }  else {
                return SmileResult.waring("认证失败");
            }
        }

    }

    @Override
    @Transactional
    public SmileResult setClientAvatar(MultipartFile file) {
        Long userID = UserUtil.getUserID();
        try {
            String s = ossFileUtil.uploadStaticFile(file, OssPathEnum.CLIENT_AVATAR.getPath(), userID + "");
            String staticFileUrl = ossFileUtil.getStaticFileUrl(s);
            LambdaUpdateWrapper<SmileClient> updateWrapper=new LambdaUpdateWrapper<>();
            updateWrapper.eq(SmileClient::getId,userID);
            updateWrapper.set(SmileClient::getClientAvatarUrl,staticFileUrl);
            smileClientService.update(updateWrapper);
            return SmileResult.sucess("头像设置成功",staticFileUrl);
        } catch (IOException e) {
            return SmileResult.error("文件上传失败");
        } catch (ClientException e) {
            return SmileResult.error("oss上传失败");
        }
    }

    @Override
    @Transactional
    public SmileResult setInfo(SmileClient smileClient) {
        Long userID = UserUtil.getUserID();
        smileClient.setId(userID);
        smileClientService.setInfo(smileClient);
        return SmileResult.sucess("用户信息更新成功",smileClient);
    }

    @Override
    public SmileResult getInfoByOpenId(String openid) {
        LambdaQueryWrapper<SmileClient> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(SmileClient::getOpenId,openid);
        SmileClient smileClient = smileClientService.getOne(queryWrapper);
        SmileClientDTO smileClientDTO = BeanCopyUtils.copyBean(smileClient, SmileClientDTO.class);

        if (smileClient==null){
            return SmileResult.waring("查无此人");
        }
        smileClientDTO.setCouponNum(couponService.getCouponNum(smileClient.getId()));
        smileClientDTO.setAlbumNum(smileAlbumService.getAlbumNum(smileClientDTO.getClientNo()));
        return SmileResult.sucess("查询成功",smileClientDTO);
    }

    @Override
    public SmileResult getclientDeliveryListByClientNo(String clientNo) {
        SmileClient user = UserUtil.getUser();
        if (user.getClientNo().equals(clientNo)){
            throw new LoginException("登录异常");
        }
        LambdaQueryWrapper<SmileClientDelivery> queryWrapper=new LambdaQueryWrapper();
        queryWrapper.eq(SmileClientDelivery::getClientId,user.getId());
        queryWrapper.orderByDesc(SmileClientDelivery::getDefaultAddress);
        List<SmileClientDelivery> clientDeliveryList = deliveryService.list(queryWrapper);
        return SmileResult.sucess(clientDeliveryList);
    }

    @Override
    @Transactional
    public SmileResult addClientDelivery(SmileClientDelivery clientDelivery) {
        Long userID = UserUtil.getUserID();
        clientDelivery.setClientId(userID);
        if (clientDelivery.getDefaultAddress()) {
            clientDeliverySubService.updDefaultAddress(userID);
        }
        deliveryService.save(clientDelivery);
        return SmileResult.sucess();
    }

    @Override
    @Transactional
    public SmileResult updClientDelivery(SmileClientDelivery clientDelivery) {
        if (clientDelivery.getDefaultAddress()) {
            clientDeliverySubService.updDefaultAddress(UserUtil.getUserID());
        }
        deliveryService.updateById(clientDelivery);
        return SmileResult.sucess();
    }


}
